package com.sunhao.springboot_satoken.config;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import com.sunhao.springboot_satoken.utils.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Sa-Token配置类
 * @author SunHao
 */
@Configuration
@Slf4j
public class SaTokenConfig implements WebMvcConfigurer {

    /**
     * 注册Sa-Token的拦截器
     * @param registry 拦截器注册表
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册Sa-Token的路由拦截器
        registry.addInterceptor(new SaInterceptor(handler -> {
            // 登录验证 -- 排除登录接口、注册接口、验证码接口
            SaRouter.match("/**")
                    .notMatch("/auth/login", "/auth/register", "/captcha/**", "/test/public")
                    .check(r -> StpUtil.checkLogin());

            // 角色验证
            SaRouter.match("/test/admin").check(r -> StpUtil.checkRole("admin"));
            SaRouter.match("/test/normal").check(r -> StpUtil.checkRole("user"));
        })).addPathPatterns("/**");
    }

    /**
     * Sa-Token全局异常处理
     */
    @RestControllerAdvice
    public static class GlobalExceptionHandler {

        /**
         * 处理未登录异常
         * @param e 未登录异常
         * @return 响应结果
         */
        @ExceptionHandler(NotLoginException.class)
        public Response handlerNotLoginException(NotLoginException e) {
            log.error("未登录异常: {}", e.getMessage());
            // 判断场景值，定制化异常信息
            String message;
            if(e.getType().equals(NotLoginException.NOT_TOKEN)) {
                message = "未提供token";
            } else if(e.getType().equals(NotLoginException.INVALID_TOKEN)) {
                message = "token无效";
            } else if(e.getType().equals(NotLoginException.TOKEN_TIMEOUT)) {
                message = "token已过期";
            } else if(e.getType().equals(NotLoginException.BE_REPLACED)) {
                message = "token已被顶下线";
            } else if(e.getType().equals(NotLoginException.KICK_OUT)) {
                message = "token已被踢下线";
            } else {
                message = "当前会话未登录";
            }
            return new Response("401", message, null);
        }

        /**
         * 处理角色异常
         * @param e 角色异常
         * @return 响应结果
         */
        @ExceptionHandler(NotRoleException.class)
        public Response handlerNotRoleException(NotRoleException e) {
            log.error("角色异常: {}", e.getMessage());
            return new Response("403", "无此角色: " + e.getRole(), null);
        }

        /**
         * 处理权限异常
         * @param e 权限异常
         * @return 响应结果
         */
        @ExceptionHandler(NotPermissionException.class)
        public Response handlerNotPermissionException(NotPermissionException e) {
            log.error("权限异常: {}", e.getMessage());
            return new Response("403", "无此权限: " + e.getPermission(), null);
        }
    }
}
